﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;
using JQuery.WebKit.Base;
using JQuery.WebKit.Interfaces;
using JQuery.WebKit.WebCommon;
using JQuery.WebKit.WebCommon.Attributes;

#region resources
[assembly: WebResource("JQuery.WebKit.JCombo.ui.dropdownchecklist.js", "text/javascript")]
[assembly: WebResource("JQuery.WebKit.JCombo.ui.dropdownchecklist.min.js", "text/javascript")]
[assembly: WebResource("JQuery.WebKit.JCombo.ui.dropdownchecklist.css", "text/css", PerformSubstitution = true)]
#endregion
namespace JQuery.WebKit
{
    [ParseChildren(typeof(JComboItem), DefaultProperty = "Items", ChildrenAsProperties = true)]
    public class JCombo : JControl, IKeyTextPair
    {
        internal override PostType PostType { get { return Base.PostType.TextAndValue; } }

        private bool _multiselect;
        public bool MultiSelect
        {
            get { return _multiselect; }
            set 
            {
                if (value == false && _firstItemCheckAll.HasValue && _firstItemCheckAll.Value == true)
                {
                    FirstItemChecksAll = null;
                }
                _multiselect = value;
            }
        }

        private bool? _firstItemCheckAll;
        [JavaScript("firstItemChecksAll", Category = "options", DefaultValue = false)]
        public bool? FirstItemChecksAll 
        {
            get { return _firstItemCheckAll; }
            set {
                _firstItemCheckAll = value;
                if (_firstItemCheckAll.HasValue && _firstItemCheckAll.Value)
                {
                    MultiSelect = true;
                }
            }
        }


        [JavaScript("forceMultiple", Category = "options", DefaultValue = false)]
        private bool? ForceMultiSelect { get; set; }

        [JavaScript("emptyText", Category = "options")]
        public string EmptyText { get; set; }

        [JavaScript("closeRadioOnClick", Category = "options", DefaultValue = false)]
        public bool? CloseOnClick { get; set; }

        [JavaScript("minWidth", Category = "options")]
        public int MinWidth { get; set; }

        [JavaScript("width", Category = "options")]
        public new int Width { get; set; }

        [JavaScript("maxDropHeight", Category = "options")]
        public int MaxDropHeight { get; set; }

        [JavaScript("maxDropWidth", Category = "options")]
        public int MaxDropWidth { get; set; }

        [JavaScript("onComplete", Category = "options")]
        public string OnComplete { get; set; }

        [JavaScript("textFormatFunction", Category = "options")]
        public string OnTextFormat { get; set; }

        [JavaScript("icon", Category = "options", DefaultValue = "{}")]
        public string Icon { get; set; }

        public bool AutoRefresh { get; set; }

        public override object Value
        {
            get
            {
                return base.Value;
            }
            set
            {
                if (base.Value != value)
                {
                    Select(value);
                }
                base.Value = value;
            }
        }

        public string KeyID { get; set; }
        public string TextID { get; set; }
        public object Key { get { return Value; } set { Value = value; } }
        public object Text { get { return TextValue; } set { TextValue = Convert.ToString(value); } }

        private string _textValue;
        public string TextValue
        {
            get
            {
                return _textValue;
            }
            set
            {
                if (_textValue != value)
                {
                    Select(value);
                }
                _textValue = value;
            }
        }

        [PersistenceMode(PersistenceMode.InnerProperty)]
        public JComboItemCollection Items
        {
            get;
            private set;
        }

        public JCombo()
            : base("select")
        {
            Items = new JComboItemCollection(this);
        }
        public JCombo(string tag)
            : base("select")
        {
            Items = new JComboItemCollection(this);
        }

        public void Select(object value)
        {
            if (value == null)
            {
                return;
            }
            if (value is Dictionary<object, object>)
            {
                Dictionary<object, object> dct = value as Dictionary<object, object>;
                bool selected = false;
                for (int i = 0; i < Items.Count; i++)
                {
                    if (!MultiSelect && selected)
                    {
                        Items[i].Selected = false;
                    }
                    else
                    {
                        KeyValuePair<object, object>? kv = dct.Where(dctItem =>
                            dctItem.Key.ToString() == Items[i].Value).FirstOrDefault();
                        if (kv.HasValue && kv.Value.Key != null)
                        {
                            Items[i].Selected = true;
                            selected = true;
                        }
                    }
                }
            }
            else if (value is Dictionary<string, JComboItem>)
            {
                Dictionary<string, JComboItem> dct = value as Dictionary<string, JComboItem>;
                bool selected = false;
                for (int i = 0; i < Items.Count; i++)
                {
                    if (!MultiSelect && selected)
                    {
                        Items[i].Selected = false;
                    }
                    else
                    {
                        KeyValuePair<string, JComboItem>? kv = dct.Where(dctItem =>
                            dctItem.Key.ToString() == Items[i].Value).FirstOrDefault();
                        if (kv.HasValue && !string.IsNullOrEmpty(kv.Value.Key))
                        {
                            Items[i].Selected = true;
                            selected = true;
                        }
                    }
                }
            }
            else if (value is KeyValuePair<object, object>)
            {
                KeyValuePair<object, object>? kv = value as KeyValuePair<object, object>?;

                for (int i = 0; i < Items.Count; i++)
                {
                    if (kv.HasValue && Convert.ToString(kv.Value.Key) == Items[i].Value)
                    {
                        Items[i].Selected = true;
                    }
                    else
                    {
                        Items[i].Selected = false;
                    }
                }
            }
            else
            {
                string val = value.ToString();
                for (int i = 0; i < Items.Count; i++)
                {
                    if (val == Items[i].Value)
                    {
                        Items[i].Selected = true;
                    }
                    else
                    {
                        Items[i].Selected = false;
                    }
                }
            }
        }

        public void Select(string text)
        {
            _textValue = text;
            if (string.IsNullOrEmpty(text))
            {
                return;
            }

            Items.ForEach(item => item.Selected = item.Text == text);
        }

        protected override void CreateChildControls()
        {
            //base.CreateChildControls();

        }

        protected override void Render(HtmlTextWriter writer)
        {
            //writer.Write("<div>");
            base.Render(writer);
            //writer.Write("</div>");
        }

        public virtual void SetDefaultValues()
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("var values = {};");
            sb.AppendLine("var skipFirstItem = $('#' + selector.id).attr('skipFirstItem');");
            sb.AppendLine("$('#' + selector.id + ' option:selected').each(function(index, value) {");
            sb.AppendLine("  var val = $(this).val();");
            sb.AppendLine("  if (skipFirstItem == 'skipFirstItem' && val == 'selectAll') {{ return true; }}");
            sb.AppendLine("  values[val] = $(this).text();");
            sb.AppendLine("});");
            sb.AppendFormat("$('#' + selector.id).attr('jValue', $.toJSON(values));");
            sb.AppendFormat("instance._updateControlText();");

            if (AutoRefresh)
            {
                JUpdater panel = this.FindParent<JUpdater>();
                if (panel != null)
                {
                    sb.AppendFormat(";$('#' + selector.id).attr('meta', 'jControl');$('#{0}').jupdater('refresh', '{1}')", panel.ClientID, this.ClientID);
                }
            }

            OnComplete = string.Format("function(instance, selector) {{ {0};{1} }}", sb.ToString(), OnComplete);

            if (!string.IsNullOrEmpty(OnTextFormat))
            {
                OnTextFormat = string.Format("function(options) {{ {0} }}", OnTextFormat);
            }

            if (!CloseOnClick.HasValue && !MultiSelect)
            {
                CloseOnClick = true;
            }

            if (MultiSelect)
            {
                ForceMultiSelect = true;
                this.Attributes.Add("multiple", "multiple");
            }

            if (_firstItemCheckAll.HasValue && _firstItemCheckAll.Value)
            { 
                this.Items.Insert(0, new JComboItem(this, "[All]", "selectAll"));
                this.Attributes.Add("skipFirstItem", "skipFirstItem");
            }

            //else
            //{
            //    if (string.IsNullOrEmpty(EmptyText) && this.Items.Count(item => item.Selected) > 0)
            //    {
            //        this.Value = this.Items.Where(item => item.Selected).First().Value;
            //    }
            //}

            if ((!Required.HasValue) || (Required.HasValue && !Required.Value && string.IsNullOrEmpty(EmptyText)))
            {
                EmptyText = "Please Select...";
            }

            if (Required.HasValue && Required.Value && this.Items.Count(item => item.Selected) > 0)
            {
                this.Value = this.Items.Where(item => item.Selected).ToDictionary(item => item.Value);
            }

            if (this.Width == 0 & !base.Width.IsEmpty && base.Width.Type == System.Web.UI.WebControls.UnitType.Pixel)
            {
                this.Width = Convert.ToInt32(base.Width.Value);
            }
            this.Items.EnsureSelection();
        }

        protected override void OnPreRender(EventArgs e)
        {
            SetDefaultValues();

            foreach (JComboItem item in Items)
            {
                this.Controls.Add(new LiteralControl(item.ToString()));
            }

            base.AddJQueryResource(Globals.ResourcePaths.JQueryLibraries.JQueryUI);
            base.AddJQueryResource("JQuery.WebKit.JCombo.ui.dropdownchecklist.js");
            base.AddCSSResource("JQuery.WebKit.JCombo.ui.dropdownchecklist.css");

            //base.AddBodyScript(string.Format("var ctrl = $('#{0}'); ctrl.dropdownchecklist({1}); ctrl.change(function() {{ ctrl.attr('value', ctrl.val()); }});", this.ClientID, this.GetJSProperties("options")));
            base.AddBodyScript(string.Format("$('#{0}').attr('jValue', $.toJSON({1})); $('#{0}').dropdownchecklist({2});", this.ClientID, GetValueAttribute(), this.GetJSProperties("options")));

            base.OnPreRender(e);
        }

        private string GetValueAttribute()
        {
            List<string> values = new List<string>();
            int idx = 0;
            foreach (JComboItem item in this.Items)
            {
                if (idx == 0 && _firstItemCheckAll == true)
                { 
                    continue;
                }
                if (!item.Selected || string.IsNullOrWhiteSpace(item.Value))
                {
                    continue;
                }
                values.Add(string.Format("\"{0}\":\"{1}\"", item.Value, item.Text));
                idx++;
            }
            return string.Format("{{ {0} }}", string.Join(", ", values));
            //{"802":"Azure Fraud Control Bureau"}
        }
    }
}
